package org.dromara.northstar.gateway.okx;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.okex.open.api.ws.BusinessWebSocketClient;
import com.okex.open.api.ws.PublicWebSocketClient;
import org.dromara.northstar.common.constant.ChannelType;
import org.dromara.northstar.common.constant.ConnectionState;
import org.dromara.northstar.common.constant.TickType;
import org.dromara.northstar.common.event.FastEventEngine;
import org.dromara.northstar.common.event.NorthstarEventType;
import org.dromara.northstar.common.model.GatewayDescription;
import org.dromara.northstar.common.model.core.Bar;
import org.dromara.northstar.common.model.core.Contract;
import org.dromara.northstar.common.model.core.Tick;
import org.dromara.northstar.gateway.IMarketCenter;
import org.dromara.northstar.gateway.MarketGateway;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;

import lombok.extern.slf4j.Slf4j;


@Slf4j
public class OkxMarketGatewayAdapter extends GatewayAbstract implements MarketGateway {
    private final FastEventEngine feEngine;

    private final IMarketCenter mktCenter;

    private final GatewayDescription gd;

    protected ConnectionState connState = ConnectionState.DISCONNECTED;

    private final PublicWebSocketClient publicWebSocketClient;

    private final BusinessWebSocketClient businessWebSocketClient;

    private volatile long lastUpdateTickTime = System.currentTimeMillis();


    //ws 模拟盘 the demo trading URL
    private static final String TEST_SERVICE_URL = "wss://wspap.okx.com:8443/ws/v5/public?brokerId=9999";
    //ws 实盘 the live trading URL
    private static final String SERVICE_URL = "wss://ws.okx.com:8443/ws/v5/public";
    //部分订阅频道已迁移
    private static final String BUSINESS_SERVICE_URL = "wss://ws.okx.com:8443/ws/v5/business";
    private static final String TEST_BUSINESS_SERVICE_URL = "wss://wspap.okx.com:8443/ws/v5/business?brokerId=9999";

    public OkxMarketGatewayAdapter(FastEventEngine feEngine, GatewayDescription gd, IMarketCenter mktCenter) {
        super(gd, mktCenter);
        OkxGatewaySettings settings = (OkxGatewaySettings) gd.getSettings();
        this.publicWebSocketClient = new PublicWebSocketClient(mktCenter, feEngine, gd.getGatewayId(), settings.getApiKey(), settings.getSecretKey(), settings.getPassphrase(), settings.getAccountType(), "public");
        this.businessWebSocketClient = new BusinessWebSocketClient(mktCenter, feEngine, gd.getGatewayId(), settings.getApiKey(), settings.getSecretKey(), settings.getPassphrase(), settings.getAccountType(), "business");
        this.feEngine = feEngine;
        this.gd = gd;
        this.mktCenter = mktCenter;
    }

    @Override
    public void connect() {
        log.debug("[{}] 欧易网关连接", gd.getGatewayId());
        if (connState == ConnectionState.CONNECTED) {
            return;
        }
        mktCenter.loadContractGroup(ChannelType.OKX);
        feEngine.emitEvent(NorthstarEventType.LOGGED_IN, gd.getGatewayId());
        feEngine.emitEvent(NorthstarEventType.GATEWAY_READY, gatewayId);
        connState = ConnectionState.CONNECTED;
    }

    @Override
    public void disconnect() {
        businessWebSocketClient.closeConnection();
        publicWebSocketClient.closeConnection();

        feEngine.emitEvent(NorthstarEventType.LOGGING_OUT, gatewayId);
        feEngine.emitEvent(NorthstarEventType.LOGGED_OUT, gatewayId);
        connState = ConnectionState.DISCONNECTED;
    }

    @Override
    public boolean getAuthErrorFlag() {
        return true;
    }

    @Override
    public boolean subscribe(Contract contract) {
        log.debug("[{}] 欧易网关订阅", gd.getGatewayId());
        OkxGatewaySettings settings = (OkxGatewaySettings) gd.getSettings();
        String symbol = contract.symbol();
        //添加订阅频道
        ArrayList<Map> channelList = new ArrayList<>();

        Map map = new HashMap();
        map.put("channel", "candle1m");
        map.put("instId", symbol);

        channelList.add(map);
        //与服务器建立连接
        BusinessWebSocketClient.connection(settings.getAccountType().equals("0") ? BUSINESS_SERVICE_URL : TEST_BUSINESS_SERVICE_URL);

        //登录账号,用户需提供 api-key，passphrase,secret—key 不要随意透漏 ^_^
        BusinessWebSocketClient.login(settings.getApiKey(), settings.getPassphrase(), settings.getSecretKey());
        BusinessWebSocketClient.subscribe(channelList);
        BusinessWebSocketClient.contractMap.put(symbol, contract);

        Map spotTickerMap = new HashMap();
        Map spotTickerMap1 = new HashMap();
        spotTickerMap.put("channel", "tickers");
        spotTickerMap.put("instId", symbol);

        spotTickerMap1.put("channel", "books5");
        spotTickerMap1.put("instId", symbol);
        channelList.clear();
        channelList.add(spotTickerMap);
        channelList.add(spotTickerMap1);
        //与服务器建立连接
        PublicWebSocketClient.connection(settings.getAccountType().equals("0") ? SERVICE_URL : TEST_SERVICE_URL);
        //登录账号,用户需提供 api-key，passphrase,secret—key 不要随意透漏 ^_^
        PublicWebSocketClient.login(settings.getApiKey(), settings.getPassphrase(), settings.getSecretKey());

        //调用订阅方法
        PublicWebSocketClient.subscribe(channelList);
        PublicWebSocketClient.contractMap.put(symbol, contract);

        return true;
    }

    @Override
    public boolean unsubscribe(Contract contract) {
        return true;
    }

    @Override
    public boolean isActive() {
        return System.currentTimeMillis() - BusinessWebSocketClient.lastUpdateTickTime < 1000;
    }

    @Override
    public ChannelType channelType() {
        return ChannelType.OKX;
    }

    @Override
    public GatewayDescription gatewayDescription() {
        gd.setConnectionState(getConnectionState());
        return gd;
    }

    @Override
    public String gatewayId() {
        return gd.getGatewayId();
    }

    @Override
    public ConnectionState getConnectionState() {
        return connState;
    }
}
